#!python
# -*- coding: utf-8 -*-

from google.appengine.api import images
from google.appengine.api import users
from google.appengine.ext import db

from django.http import Http404
from django.utils.translation import ugettext as _

from common import redirect, respond, render
from models import Album, Picture
from django.conf import settings
from django.http import HttpResponse
from django.core.servers.basehttp import FileWrapper
from datetime import datetime, timedelta

import os, cgi, tempfile, zipfile, urllib, StringIO

_params = {'menu_album': True,
           'title': _("albums"),}

def create(request):
    if request.method == 'GET':
        return respond('album_edit.html', _params)
    elif request.method == 'POST':
        album_name = request.POST.get('album_name')
        user = users.get_current_user()
        album_key = Album(name=album_name,
                          creator=user).put()

        return redirect("/album/%s" % album_key.id())

def edit(request, album_id):
    try:
        album = get_album(album_id, check_authority=True)
    except Exception:
        return redirect('/album')

    if request.method == 'GET':
        params = _params.copy()
        params.update({'title': album.name,
                       'album': album,
                       'in_form': True,
                       'pictures': album.pictures})
        return respond('album_edit.html', params)
    elif request.method == 'POST':
        cover = request.POST.get('cover')
        try:
            cover = Picture.get_by_id(int(cover))
            if cover is None:
                raise
        except:
            cover = None        # might be caused by wrong id
        album.name = request.POST.get('album_name')
        album.cover = cover
        album.put()
        return redirect("/album/%s" % album_id)

def upload(request, album_id):
    try:
        album = get_album(album_id, check_authority=True)
    except Exception:
        return redirect('/album')

    if request.method == 'GET':
        params = _params.copy()
        params.update({'title': album.name,
                       'album': album,})
        return respond('picture_upload.html', params)
    elif request.method == 'POST':
        my_file = request.FILES.get('picfile')
        try:
            pic = Picture.process_upload(my_file,
                                         album=album,
                                         user=users.get_current_user(),)
            if album.cover is None:
                album.cover = pic
                album.put()
            return respond('redirect.html', {'msg': _("upload success"),
                                             'redirect': "/picture/%s/edit" % pic.key().id(),})
        except images.BadImageError:
            return feedback(album, err=_("bad image"))
        except images.NotImageError:
            return feedback(album, err=_("not image"))
        except images.LargeImageError:
            return feedback(album, err=_("large_image"))

def home(request):
    try:
        page_number = int( request.GET.get('page') )
    except:
        page_number = 1
    offset = (page_number - 1) * settings.LM_ALBUMS_PER_PAGE
    try:
        albums = db.Query(Album).order('-created_date').fetch(settings.LM_ALBUMS_PER_PAGE, offset)
    except:
        albums = None
    params = _params.copy()
    if albums is not None:
        params.update({'albums': albums,})
    if Album.all().count() > page_number * settings.LM_ALBUMS_PER_PAGE:
        params.update({'next_page': page_number + 1})
    if page_number > 1:
        params.update({'previous_page': page_number - 1})
    return respond('album_home.html', params)

def detail(request, album_id):
    try:
        album = get_album(album_id)
    except Exception:
        return redirect('/album')

    try:
        page_number = int( request.GET.get('page') )
    except:
        page_number = 1

    offset = (page_number - 1) * settings.LM_PICTURES_PER_PAGE
    params = _params.copy()
    params.update({'title': album.name,
                   'album': album,
                   'pictures': album.pictures.fetch(settings.LM_PICTURES_PER_PAGE, offset)})
    if album.pictures.count() > page_number * settings.LM_PICTURES_PER_PAGE:
        params.update({'next_page': page_number + 1})
    if page_number > 1:
        params.update({'previous_page': page_number - 1})
    return respond('album_detail.html', params)

def slug(request, year, month, day, name):
    year = int(year)
    month = int(month)
    day = int(day)
    created_date = datetime(year, month, day) # not used yet.
    query = Album.all()
    query.filter('name =', name)
    query.filter('created_date >', created_date)
    query.filter('created_date <', created_date + timedelta(days=1))
    if query.count() > 1 or query.count() == 0:
        return redirect('/album')

    album = query.get()
    return detail(request, album.key().id())

def delete(request, album_id):
    try:
        album = get_album(album_id, check_authority=True)
    except Exception:
        return redirect('/album/%s' % album_id)

    if request.GET.has_key('confirm'):
        for pic in album.pictures:
            pic.delete()
        album.delete()
        return respond('redirect.html', {'redirect': '/album',
                                         'msg': _('album delete success')})
    else:
        return respond('confirm.html', {'confirm_url': '/album/%s/delete?confirm' % album_id,
                                        'cancel_url': '/album/%s' % album_id,
                                        'album': album,
                                        'title': album.name,})

def export(request, album_id):
    """
    File has maximum size of 1MB.
    Hence, 1) the result will be zipped, 2) only the thumbnails will be exported.
    """
    try:
        album = get_album(album_id)
    except:
        return redirect('/album')

    temp = tempfile.TemporaryFile()
    archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED)
    for pic in album.pictures:
        pic_file = StringIO.StringIO(pic.thumbnail_data)
        archive.writestr( '%s.jpg' % pic.key().id(), pic_file.read( len(pic.thumbnail_data) ) )

    album_text_str = render('album_export.yaml', { 'album': album })
    album_text = StringIO.StringIO(album_text_str.encode('utf-8'))
    archive.writestr( 'essay.txt', album_text.read( len(album_text_str) ) )

    archive.close()
    wrapper = FileWrapper(temp)
    response = HttpResponse(wrapper, content_type='application/zip')
    response['Content-Disposition'] = 'attachment; filename=%s.zip' % album.key().id()
    response['Content-Length'] = temp.tell()
    temp.seek(0)
    return response

def get_album(album_id, check_authority=False):
    album = Album.get_by_id(int(album_id))
    if album is None:
        raise Http404
    elif check_authority and album.creator != users.get_current_user():
        raise Exception('authorize_error')
    else:
        return album


def feedback(album, **kargs):
    params = {'redirect': '/album/%s' % album.key().id(),
              'album': album,}
    if kargs.get('err'):
        params.update({'err': kargs.get('err')})
    elif kargs.get('msg'):
        params.update({'msg': kargs.get('msg')})
    return respond('redirect.html', params)
